(** Géométrie. *)

(** Valeur approchée de Pi. *)
let pi = 4. *. atan 1.

(** Point ou vecteur. *)
type point = { x : float; y : float; }
type vecteur = point 

type cercle = { c : point; r : float; }
type segment = { p1 : point; p2: point; }


type surface =
  | Circle of point * float (** Cercle : centre et rayon *)
  | Line of point * point   (** Segment : deux extremites *)
  | Polygon of point list   (** Polygone plein : listes des sommets *)



(** Constructeur de point. *)
let point a b = {x=a;y=b}

(** Opérateurs infixes sur les vecteurs. *)
let (+|) p v = {
  x=p.x+.v.x;
  y=p.y+.v.y
}

let (-|) p v = {
  x=p.x-.v.x;
  y=p.y-.v.y
}
  
let (~|) p = {
  x=(-.p.x);
  y=(-.p.y)
}

let ( *|) fact p = {
  x=p.x*.fact;
  y=p.y*.fact
}

(** Vecteur normal d'un vecteur. *)
let normal p = {
  x=(-.p.y);
  y=p.x
}

(** Produit scalaire de deux vecteurs. *)
let dot p1 p2 = p1.x*.p2.x+.p1.y*.p2.y

(** Carré scalaire d'un vecteur. *)
let sqdot p = dot p p

(** Norme d'un vecteur. *)
let length p = sqrt ((p.x**2.)+.(p.y**2.))

(** Vecteur unitaire d'un vecteur. *)
let unitise p = 
  let norme = length p in
  if norme = 0. then failwith "Division par zero"
  else
    {
      x=p.x/.norme;
      y=p.y/.norme
    }

(* Distance entre deux points. *)
let distance p1 p2 = sqrt (((p2.x-.p1.x)**2.)+.((p2.y-.p1.y)**2.))

(* Ajoute un angle à un vecteur. *)
let rotate p angle = {
  x=p.x *. cos angle +. p.y *. sin angle;
  y=p.x *. -1. *. sin angle +. p.y *. cos angle
}

(* coeff directeur d'une droite passant par les deux points *)
let coeffDir p1 p2 =
	  let res = (p2.y-.p1.y)/.(p2.x -. p1.x) in
		if res = infinity then
			1e+300
		else if res = neg_infinity then
			(-1e+300)
		else 
			res


let vecto v1 v2 =
	(v1.x*.v2.y)-.(v1.y*.v2.x)


(* Definit si deux segments se croisent ou non*)
let seCroisent s1 s2 =
  let (x1,y1) = (s1.p1.x,s1.p1.y) in
  let (x2,y2) = (s1.p2.x,s1.p2.y) in
  let (x3,y3) = (s2.p1.x,s2.p1.y) in
  let (x4,y4) = (s2.p2.x,s2.p2.y) in
  let a1 = coeffDir {x=x1;y=y1} {x=x2;y=y2} in
  let a2 = coeffDir {x=x3;y=y3} {x=x4;y=y4} in
  let b1 = y1 -. (a1 *. x1) in
  let b2 = y3 -. (a2 *. x3) in
  if a1=a2 then
    false
  else
    let xcommun = (b2-.b1)/.(a1-.a2) in
    let estEntre el borne1 borne2 =
      if borne1 < borne2 then
        borne1<=el && borne2>=el
      else
	borne1>=el && borne2<=el
    in
    (estEntre xcommun x1 x2) && (estEntre xcommun x3 x4)
(*
let seCroisent s1 s2 =
	let vint1 = {p1=s1.p1;p2=s2.p1} in
	let a = (vecto s1 vint1) /. (length s1) in
	let vint2 = {p1=s1.p1;p2=s2.p2} in
	let b = (vecto s1 vint2) /. (length s1) in
	let nouveauB = (length s2) +. (((length s2)*.b)/.(a-.b)) in
	let vraiRapport = nouveauB/.(length s2) in
	let resX = s2.p1.x+.s2
*)
	
    
(* Definit le point commun de deux segments si ils se croisent *)
let pointCommun s1 s2 =
	if not (seCroisent s1 s2) then
		failwith "Ne se croisent pas"
	else
		let (x1,y1) = (s1.p1.x,s1.p1.y) in
  		let (x2,y2) = (s1.p2.x,s1.p2.y) in
  		let (x3,y3) = (s2.p1.x,s2.p1.y) in
  		let (x4,y4) = (s2.p2.x,s2.p2.y) in
  		let a1 = (y2-.y1) /. (x2 -. x1) in
  		let a2 = (y4-.y3) /. (x4 -. x3) in
  		let b1 = y1 -. (a1 *. x1) in
  		let b2 = y3 -. (a2 *. x3) in
		let xcommun = (b2-.b1)/.(a1-.a2) in
		let ycommun = a1 *. xcommun +. b1 in
		{x=xcommun;y=ycommun}
		
		 





;;  
